<template>
  <!--  <div>-->
  <div class="map" :style="{width: width,height: height}">
    <div class="search-div" style="z-index: 2147483647; position: absolute;left: 30px;top:30px;">
    </div>
    <div v-if="legendUrl" style="z-index: 2147483647; position: absolute;left: 63%;top:30px;">
      <img :src="legendUrl">
    </div>
    <div class="map-content"
         v-loading="loading">
      <!-- 地图 -->
      <div :id="mapId" style="width: 100%;height: 100%"></div>


      <!-- 工具 -->
      <el-card class="map-tools"
               :body-style="{ padding: '5px' }" v-if="mapTools.length">
        <template v-for="(tool, index) in mapTools">
          <el-tooltip :key="index"
                      :content="tool.label"
                      effect="dark"
                      placement="bottom">
            <i :class="['tool-icon', tool.icon]"
               @click="handleToolClick(tool)">
            </i>
          </el-tooltip>
        </template>
      </el-card>

      <div v-show="showMapTooltip"
           class="map-tooltip"
           ref="mapTooltip">
        {{ mapTooltipText }}
      </div>

      <!-- 信息窗口 -->
      <transition name="el-fade-in-linear">
        <info-window ref="infoWindow"
                     v-if="infoWindow.visible"
                     :title="infoWindow.extData.title"
                     :pos="infoWindow.position"
                     @close="infoWindowClose">
          <el-form ref="polygonForm" :model="infoWindow.extData" :rules="polygonFormRules" :inline="true"
                   v-show="infoWindow.isEditAttribute">

            <el-form-item v-for="(item, index) in polygonForm" :key="index" :label="item.name" :prop="item.field">
              <el-select v-model="infoWindow.extData[item.field]" placeholder="请选择" v-if="item.type=='select'">
                <el-option v-for="dict in getDictDatas(DICT_TYPE[item.dictKey])"
                           :key="dict.value" :label="dict.label" :value="parseInt(dict.value)"/>
              </el-select>
              <el-input v-model="infoWindow.extData[item.field]" :placeholder="'请输入' + item.name" v-else/>
            </el-form-item>

          </el-form>
          <el-form size="mini" v-show="!infoWindow.isEditAttribute">
            <el-form-item v-for="(item, index) in polygonForm" :key="index" :label="item.field==='img'?'':item.name">
              <span v-if="item.dictKey">
                <dict-tag :type="DICT_TYPE[item.dictKey]" :value="item.value"/>
              </span>
              <img v-else-if="item.field==='img'" :src="item.value" style="width: 100%;"/>
              <span v-else>{{ item.value }}</span>
            </el-form-item>
          </el-form>
          <div slot="footer" class="info-window-footer" v-show="!disabled">
            <span class="by"></span>
            <div class="tools">
              <template v-for="(tool, index) in infoWindowTools">
                <el-tooltip :key="index"
                            effect="dark"
                            :content="tool.label"
                            placement="top">
                  <i :class="['footer-icon', tool.icon]"
                     @click="infoWindowToolClick(tool)"></i>
                </el-tooltip>
              </template>
            </div>
          </div>
        </info-window>
      </transition>

      <!-- 图层弹框 -->
      <transition name="slide-fade">
        <div class="dialog" v-show="isShowLayer">
          <div class="title-layer">图层</div>
          <ul class="layer-list">
            <li v-for="(layer, index) in layerList" :key="index" v-show="layer.show">
              <el-checkbox v-model="layer.checked" @change="customerLayerHandle(index, $event)"
                           style="vertical-align: top">{{ layer.name }}
              </el-checkbox>
              <div class="el-color-predefine__color-selector" style="display: inline-block">
                <div :style="'background-color:' + layer.color" class=""></div>
              </div>
              <div class="block">
                <span class="demonstration">透明度</span>
                <el-slider v-model="layer.opacity" @change="changeLayerOpacity(index,$event)"></el-slider>
              </div>
            </li>
          </ul>
        </div>
      </transition>
      <!-- 遮罩 -->
      <div v-show="isShowLayer" class="mask" @click.stop="handleSwitchLayer"></div>
      <slot name="work"></slot>
      <slot name="search" v-if="showSearchChange"></slot>

    </div>
  </div>

</template>

<script>
import 'ol/ol.css'
import {Feature, Map, Overlay, View} from 'ol'
import {defaults as defaultControls} from 'ol/control'
import {boundingExtent, getCenter} from 'ol/extent'
import {MultiPoint, Point, Polygon} from 'ol/geom'
import {defaults as defaultInteractions, Draw, Modify, Snap} from 'ol/interaction'
import {GeoJSON, WFS} from 'ol/format'
import {and as andFilter, equalTo as equalToFilter, like as likeFilter,} from 'ol/format/filter';
import {Cluster, ImageWMS, Vector as VectorSource, WMTS, XYZ} from 'ol/source'
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer'
import {Circle, Fill, Icon, Stroke, Style, Text} from 'ol/style'

import {easeOut} from 'ol/easing';
import {getVectorContext} from 'ol/render';
import {unByKey} from 'ol/Observable';

import {addCoordinateTransforms, addProjection, Projection, transform} from 'ol/proj'
import proj4 from 'proj4';
import {register} from 'ol/proj/proj4'
import {bbox} from 'ol/loadingstrategy';
import {
  area as turfArea,
  booleanOverlap as turfBooleanOverlap,
  booleanWithin as turfBooleanWithin,
  polygon as turfPolygon
} from '@turf/turf'
import InfoWindow from "@/components/DtszMap/info-window";
import WMTSTileGrid from "ol/tilegrid/WMTS";

export default {
  components: {
    InfoWindow,
    // StyleSetting,
    // EditStyleDialog
  },
  props: {
    mapId: {
      type: String,
      default: "GDMap",
    },
    width: {
      type: String,
      default: "100%",
    },
    height: {
      type: String,
      default: "100%",
    },
    disabled: { // 是否全局禁止操作
      type: Boolean,
      default: false
    },
    polygonStyle: { // 多边形样式
      type: Object,
      default: () => {
        return {
          fillColor: '#409EFF', // 填充色
          fillOpacity: 0.2, // 填充透明度
          strokeColor: '#ffff00', // 轮廓颜色
          // strokeColor: '#409EFF', // 轮廓颜色
          strokeWeight: 1, // 轮廓宽度
          strokeOpacity: 0.9 // 轮廓透明度
        }
      },
    },
    polygonSelectStyle: { // 多边形选中时样式
      type: Object,
      default: () => {
        return {
          fillColor: '#faf155', // 填充色
          fillOpacity: 0.5, // 填充透明度
          strokeColor: '#ffff00', // 轮廓颜色
          strokeWeight: 1, // 轮廓宽度
          strokeOpacity: 0.9 // 轮廓透明度
        }
      },
    },
    polygonForm: { // 多边形form表单参数
      type: Array,
      default: () => [],
    },
    polygonFormRules: { // 多边形form表单验证规则
      type: Object,
      default: () => {
      },
    },
    center: { // 地图默认显示的中心位置
      type: Array,
      default: () => [],
    },
    operations: { // 地图多边形可操作的选项
      type: Array,
      default: () => ['add', 'edit-attribute', 'edit-node', 'delete'],
    },
    tools: {
      type: String,
      default: () => 'polygon',
    },
    useWfs: {
      type: Boolean,
      default: false
    },
    wfsFeatureName: {
      type: String,
      default: ''
    },
    contractSign: {
      type: Boolean,
      default: false
    },
    largeScreenPlot: {
      type: Boolean,
      default: false
    },
    // 是否显示搜索框
    showSearch: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      GDMap: null,
      source: null,
      vector: null,
      modify: null,
      draw: null,
      snap: null,
      drawPointCount: 0,
      isDrawing: false,
      showMapTooltip: false,
      mapTooltipText: '单击进行绘制',
      checkList: [],
      originalPolygons: [],
      polygons: [],
      editPolygons: [],
      mapLoading: true,
      dataLoading: true,
      // mapTools: this.getMapTools(),
      editStyleDialog: {
        styles: null,
        polygonId: ''
      },
      styles: {
        polygon: {
          fillColor: '#409EFF', // 填充色
          fillOpacity: 0.2, // 填充透明度
          strokeColor: '#ffff00', // 轮廓颜色
          // strokeColor: '#409EFF', // 轮廓颜色
          strokeWeight: 1, // 轮廓宽度
          strokeOpacity: 0.9 // 轮廓透明度
        }
      },
      infoWindow: {
        overlay: null,
        extData: {},
        polygonIndex: null,
        polygonCenter: null,
        featureIndex: null,
        feature: null,
        visible: false,
        isEditAttribute: false,
        position: null
      },
      // 查询参数
      queryParams: {
        keyworlds: null
      },
      form: {},
      isShowLayer: false,
      activeMap: 'yx',
      layerList: [
        {
          name: '草木',
          checked: false,
          opacity: 100,
          color: '#0D714B',
          show: true,
          layerObj: new TileLayer({
            extent: [115.88611563697911, 31.7457367956912, 116.22357116343723, 32.0015079511837],
            source: new XYZ({
              url: 'https://map.dutkj.com/gwc/service/tms/1.0.0/dtsz%3ACM@4490/{z}/{x}/{-y}.png',
              maxZoom: 18,
              zIndex: 3
            })
          })
        },
        {
          name: '建筑',
          checked: false,
          opacity: 100,
          color: '#FF5500',
          show: true,
          layerObj: new TileLayer({
            extent: [115.88611563697911, 31.7457367956912, 116.22357116343723, 32.0015079511837],
            source: new XYZ({
              url: 'https://map.dutkj.com/gwc/service/tms/1.0.0/dtsz%3AJZDL@4490/{z}/{x}/{-y}.png',
              maxZoom: 18,
              zIndex: 3
            })
          })
        },
        {
          name: '水源',
          checked: false,
          opacity: 100,
          color: '#73DFFF',
          show: true,
          layerObj: new TileLayer({
            extent: [115.88611563697911, 31.7457367956912, 116.22357116343723, 32.0015079511837],
            source: new XYZ({
              url: 'https://map.dutkj.com/gwc/service/tms/1.0.0/dtsz%3ASY@4490/{z}/{x}/{-y}.png',
              maxZoom: 18,
              zIndex: 3
            })
          })
        },
        {
          name: '种植分布',
          checked: false,
          opacity: 100,
          color: '#55FF00',
          show: true,
          layerObj: new TileLayer({
            extent: [115.88611563697911, 31.7457367956912, 116.22357116343723, 32.0015079511837],
            source: new XYZ({
              url: 'https://map.dutkj.com/gwc/service/tms/1.0.0/dtsz%3AZZFB@4490/{z}/{x}/{-y}.png',
              maxZoom: 18,
              zIndex: 3
            })
          })
        },
      ],
      filterArr: [],
      tileLayer: null,
      cityLayerFlag: true,
      markSource: null,
      markLayer: null,
      pointLayer: null,
      showSearchChange: this.showSearch,
      legendUrl: ''
    }
  },
  created() {
    // this.cityLayerFlag = true;
  },
  mounted() {
    this.source = new VectorSource({
      format: new GeoJSON(),
      loader: (extent) => {
        this.wfsLoad(extent)
        if (this.cityLayerFlag === true) {
          // this.layerList[4].layerObj.setZIndex(5)
          // this.customerLayerHandle(4, true)
          this.cityLayerFlag = false;
        }
      },
      strategy: bbox
    })

    this.editSource = new VectorSource()
    this.vector = new VectorLayer({
      source: this.source,
      zIndex: 4
    })

    this.markSource = new VectorSource()
    const styleCache = {};
    this.markLayer = new VectorLayer({
      source: new Cluster({
        distance: 30,
        minDistance: 5,
        source: this.markSource,
      }),
      style: function (feature) {
        const size = feature.get('features').length;
        let style = styleCache[size];
        if (!style) {
          style = new Style({
            image: new Icon({
              anchor: [0.5, 1],
              offset: [36, 22],
              size: [18, 26],
              src: require('@/assets/icons/map/ic_marker.png')
            })
          });
          styleCache[size] = style;
        }
        return style;
      },
    });

    // 注册4490坐标系
    proj4.defs("EPSG:4490", "+proj=longlat +ellps=GRS80 +no_defs");
    register(proj4);
    const projection_4490 = new Projection({
      code: 'EPSG:4490',
      units: 'degrees',
      axisOrientation: 'neu'
    });
    projection_4490.setExtent([-180, -90, 180, 90])
    projection_4490.setWorldExtent([-180, -90, 180, 90])
    addProjection(projection_4490)
    addCoordinateTransforms('EPSG:4326', 'EPSG:4490',
      function (coordinate) {
        return proj4('EPSG:4326', 'EPSG:4490', coordinate)
      },
      function (coordinate) {
        return proj4('EPSG:4490', 'EPSG:4326', coordinate)
      }
    )

    let resolutions_4490 = [
      1.40625,
      0.703125,
      0.3515625,
      0.17578125,
      0.087890625,
      0.0439453125,
      0.02197265625,
      0.010986328125,
      0.0054931640625,
      0.00274658203125,
      0.001373291015625,
      6.866455078125e-4,
      3.4332275390625e-4,
      1.71661376953125e-4,
      8.58306884765625e-5,
      4.291534423828125e-5,
      2.1457672119140625e-5,
      1.0728836059570312e-5,
      5.364418029785156e-6,
      2.682209064925356e-6,
      1.3411045324626732e-6,
      6.705522662313365e-7,
    ]

    // 高德地图
    const gdLayer = new TileLayer({
      source: new XYZ({
        url: 'http://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=6&x={x}&y={y}&z={z}'
      })
    });

    // 天地图
    const tdLayer = new TileLayer({
      source: new XYZ({
        url: 'http://t0.tianditu.com/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={z}&TileRow={y}&TileCol={x}&style=default&format=tiles&tk=1cab1a7066d3968ba1dc26ed0289ad9e',
      })
    });

    const fxpcSatelliteLayer = new TileLayer({
      source: new XYZ({
        url: 'https://fxpc.mem.gov.cn/data_preparation/a12eadf6-1a57-43fe-9054-2e22277bd553/4eb4b664-5633-4ab3-b0fd-345829dd3a87/wmts?layer=img&style=default&tileMatrixSet=c&service=wmts&request=gettile&version=1.0.0&format=tiles&tileMatrix={z}&tileCol={x}&tileRow={y}&geokey=2CA54B6D242305ABF3822EC38D121CD9',
        projection: projection_4490,
        maxZoom: 18,
        zIndex: 0
      })
    });

    const fxpcSatelliteRoadSignLayer = new TileLayer({
      source: new XYZ({
        url: 'https://fxpc.mem.gov.cn/data_preparation/a12eadf6-1a57-43fe-9054-2e22277bd553/83e5b643-edc3-4118-ba04-2a9186606b42/wmts?layer=cia&style=default&tileMatrixSet=c&service=wmts&request=gettile&version=1.0.0&format=tiles&tileMatrix={z}&tileCol={x}&tileRow={y}&geokey=2CA54B6D242305ABF3822EC38D121CD9',
        projection: projection_4490,
        maxZoom: 18,
        zIndex: 2
      })
    });
    // 自定义高精度卫星切片
    var custLayer = new TileLayer({
      source: new WMTS({
        url: 'https://map.dutkj.com/gwc/service/wmts',
        layer: 'dtsz:HONGJI',
        matrixSet: 'WebMercatorQuad',
        format: 'image/png',
        projection: 'EPSG:3857',
        tileGrid: new WMTSTileGrid({
          tileSize: [256, 256],
          extent: [-2.003750834E7, -2.0037508345578436E7, 2.0037508345578436E7, 2.003750834E7],
          origin: [-2.003750834E7, 2.003750834E7],
          resolutions: [156543.03392804076, 78271.51696402022, 39135.75848201011, 19567.879241005117, 9783.939620502542, 4891.969810251271, 2445.9849051256383, 1222.9924525628178, 611.4962262814075, 305.7481131407024, 152.8740565703523, 76.43702828517615, 38.21851414258808, 19.10925707129404, 9.55462853564699, 4.777314267823495, 2.388657133911756, 1.1943285669558765, 0.5971642834779383, 0.29858214173896913, 0.14929107086948457, 0.07464553543474216, 0.03732276771737108, 0.018661383858685567, 0.009330691929342784],
          matrixIds: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24']
        }),
        style: '',
        wrapX: true,
        zIndex: 1
      })
    })

    this.GDMap = new Map({
      target: this.mapId,
      controls: defaultControls({
        zoom: false
      }),
      layers: [
        fxpcSatelliteLayer,
        custLayer,
        fxpcSatelliteRoadSignLayer,
        this.vector,
        this.markLayer
      ],
      view: new View({
        center: this.center.length ? transform(this.center, "EPSG:4326", "EPSG:4490") : transform([116.1733, 31.9137], "EPSG:4326", "EPSG:4490"),
        // center: this.center.length ? transform(this.center, "EPSG:4326", "EPSG:3857") : [13087853.731100908, 3652314.085522261],
        zoom: 14,
        resolutions: resolutions_4490,
        projection: projection_4490,
      }),
      interactions: new defaultInteractions({
        doubleClickZoom: false,   //屏蔽双击放大事件
      })
    })
    // 强制更新地图数据，防止部分情况初始化的时候地图被拉伸
    setTimeout(() => {
      this.GDMap.updateSize()
    }, 20)
    // 用于编辑
    this.modify = new Modify({
      source: this.editSource,
      style: new Style({
        image: new Circle({
          radius: 3,
          fill: new Fill({
            color: '#409EFF'
          })
        })
      })
    })
    // 交互点吸附
    this.snap = new Snap({
      source: this.source,
      pixelTolerance: 5
    })
    this.mapLoading = false
    this.initEvent()
    let sourceShowByZoom = false;

    this.GDMap.getView().on('change:resolution', () => {

      if (!this.contractSign) {
        if (this.GDMap.getView().getZoom() > 16) {
          if (this.useWfs && !sourceShowByZoom) {
            sourceShowByZoom = true
            this.source.clear(true)
            this.source.refresh()
          }
          this.vector.setVisible(true)
          if (this.markLayer) {
            this.markLayer.setVisible(false)
          }
        } else {
          sourceShowByZoom = false
          this.vector.setVisible(false)
          if (this.markLayer) {
            this.markLayer.setVisible(true)
          }
        }
        this.contractSign = false
      }
    });
  },
  computed: {
    loading() {
      return this.mapLoading
    },
    infoWindowTools() {
      let tools = []
      if (this.infoWindow.isEditAttribute) {
        if (this.operations.indexOf('add') >= 0 || this.operations.indexOf('edit-attribute') >= 0) {
          tools = [
            {
              name: 'complate',
              label: '完成',
              icon: 'el-icon-check'
            }
          ]
        }
      } else {
        if (this.operations.indexOf('edit-node') >= 0) {
          tools.push({
            name: 'editNode',
            functionName: 'EditAreaNode',
            label: '开启/结束编辑节点',
            icon: 'el-icon-menu'
          })
        }
        if (this.operations.indexOf('edit-attribute') >= 0) {
          tools.push({
            name: 'editAttribute',
            functionName: 'EditAreaAttributes',
            label: '编辑属性',
            icon: 'el-icon-edit'
          })
        }
        if (this.operations.indexOf('delete') >= 0) {
          tools.push({
            name: 'delete',
            functionName: 'DelArea',
            label: '删除',
            icon: 'el-icon-delete'
          })
        }
      }
      return tools
    },
    mapTools() {
      let mapTools = []
      if (this.tools.indexOf('search') >= 0) {
        mapTools.push({
          name: 'search',
          functionName: 'AddArea',
          label: '搜索房屋',
          icon: this.searchIcon
        })
      }
      if (this.tools.indexOf('polygon') >= 0) {
        if (!this.disabled && this.operations.indexOf('add') >= 0) {
          mapTools.push({
            name: 'polygon',
            functionName: 'AddArea',
            label: '添加区域',
            icon: 'el-icon-plus'
          })
        }
      }
      if (this.tools.indexOf('layer') >= 0) {
        mapTools.push({
          name: 'layer',
          functionName: 'AddArea',
          label: '图层',
          icon: 'el-icon-copy-document'
        })
      }
      return mapTools
    },
    searchIcon() {
      if (this.showSearchChange) {
        return 'el-icon-close'
      } else {
        return 'el-icon-search'
      }
    }
  },
  methods: {
    search(form, filter, callback) {
      this.filterArr = [];
      for (let field in form) {
        if (form[field] == null) {
          continue;
        }
        let temp = {
          field: field,
          value: form[field],
          filter_type: filter[field] ?? 'equal'
        }
        this.filterArr.push(temp);
      }
      this.wfsLoad('', () => {
        this.GDMap.getView().fit(this.source.getExtent())
        if (callback) {
          callback()
        }
      })
    },
    //地块或者图斑的红色箭头标记物
    coordinateClusters() {
      const features = this.source.getFeatures();
      const markFeatures = [];
      features.forEach((v) => {
        markFeatures.push(new Feature(new Point(this.getFeatureCenter(v))));
      })
      this.markSource.clear(true)
      this.markSource.addFeatures(markFeatures)
    },

    flash(feature) {
      const duration = 3000;
      const start = Date.now();
      let center = this.getFeatureCenter(feature)
      const flashGeom = new Feature(new Point(center)).getGeometry();
      const listenerKey = this.GDMap.getLayers().getArray()[0].on('postrender', (event) => {

        const frameState = event.frameState;
        const elapsed = frameState.time - start;
        if (elapsed >= duration) {
          unByKey(listenerKey);
          return;
        }
        const vectorContext = getVectorContext(event);
        const elapsedRatio = elapsed / duration;
        // radius will be 5 at start and 30 at end.
        const radius = easeOut(elapsedRatio) * 25 + 5;
        const opacity = easeOut(1 - elapsedRatio);

        const style = new Style({
          image: new Circle({
            radius: radius,
            stroke: new Stroke({
              color: 'rgba(255, 215, 0, ' + opacity + ')',
              width: 0.25 + opacity,
            }),
          }),
        });

        vectorContext.setStyle(style);
        vectorContext.drawGeometry(flashGeom);
        // tell OpenLayers to continue postrender animation
        this.GDMap.render();
      });
    },
    // customerLayerHandle(index, isShow) {
    //   let layerObj = this.layerList[index].layerObj
    //   if (isShow) {
    //     this.GDMap.addLayer(layerObj)
    //   } else {
    //     this.GDMap.removeLayer(layerObj)
    //   }
    // },
    // changeLayerOpacity(index, opacity) {
    //   let layerObj = this.layerList[index].layerObj
    //   //修改选中图层的透明度属性
    //   layerObj.setOpacity(opacity / 100)
    // },
    getFilter() {
      if (this.filterArr.length === 0) {
        return null
      }
      let conditions = []
      this.filterArr.forEach((item) => {
        let filterObj;
        if (item.filter_type == 'equal') {
          filterObj = equalToFilter(item.field, item.value)
        } else {
          filterObj = likeFilter(item.field, '*' + item.value + '*')
        }
        conditions.push(filterObj)
      })

      if (conditions.length === 1) {
        return conditions[0]
      } else {
        return andFilter.apply(null, conditions)
      }
    },
    wfsLoad(extent = '', callback) {
      if (!this.useWfs) {
        return false
      }
      const filter = this.getFilter()
      let option = {
        srsName: 'EPSG:4490',
        featureNS: 'http://www.opengeospatial.net/dtsz',
        featurePrefix: 'dtsz',
        // featureTypes: ['worldtest'],
        featureTypes: [this.wfsFeatureName],
        outputFormat: 'application/json',
        geometryName: 'shape',
      }
      if (filter != null) {
        option.filter = filter
      } else {
        if (this.GDMap.getView().getZoom() < 16) {
          return false
        }
        option.bbox = extent
      }


      // 创建一个请求
      const featureRequest = new WFS().writeGetFeature(option);
      // 发送请求
      return fetch('https://map.dutkj.com/wfs', {
        method: 'POST',
        body: new XMLSerializer().serializeToString(featureRequest)
      }).then(function (response) {
        return response.json()
      }).then((json) => {
        this.source.clear();
        this.polygons = []
        const features = new GeoJSON().readFeatures(json);
        this.source.addFeatures(features)
        // 添加点击事件
        features.forEach((feature) => {

          let {geometry, ...polygon} = feature.getProperties()

          feature.setId(polygon.id)

          polygon.style = polygon.style ? JSON.parse(polygon.style) : this.polygonStyle

          this.polygonSetStyle(feature, polygon.style)

          this.polygons.push(polygon)

          feature.setProperties({
            styles: polygon.style,
            extData: polygon
          })

          feature.on('click', (ev) => {
            // console.log("ev"+ev);
            const current_feature = ev.target
            const point = ev.event.coordinate
            this.setInfoWindowPosition(current_feature, point)
          })
        })
      }).then(() => {
        if (callback) {
          callback()
        }
      })
    },
    initEvent() {
      this.mapClickEvent = this.GDMap.on('click', (ev) => {
        if (this.isDrawing) {
          this.drawPointCount++
        }
        this.GDMap.forEachFeatureAtPixel(ev.pixel, (feature) => {
          feature.dispatchEvent({type: 'click', event: ev})
        })
      })
      this.mapPointermoveEvent = this.GDMap.on('pointermove', (ev) => {
        if (this.isDrawing) {
          this.showMapTooltip = true
          if (this.$refs.mapTooltip) {
            const pixel = ev.pixel
            this.setMapTooltipPosition(pixel)
          }
        }
      })
    },
    handleSetStyle() {
      if (this.checkList.length) {
        this.$refs.styleSetting.show()
      } else {
        this.$message.error('请勾选需要批量修改样式的区域')
      }
    },
    styleSettingConfirm(styles) {
      const features = this.source.getFeatures()
      const polygons = this.polygons
      features.forEach(item => {
        const id = item.getId()
        if (this.checkList.indexOf(id) > -1) {
          this.polygonSetStyle(item, styles)
        }
      })
      polygons.forEach(item => {
        if (this.checkList.indexOf(item.id) > -1) {
          item.styles = styles
        }
      })
      this.$refs.styleSetting.hide()
    },
    handleToolClick(tool) {
      switch (tool.name) {
        // 画多边形
        case 'polygon':
          this.handleDrawPolygon(tool)
          break
        // 图层
        case 'layer':
          this.handleSwitchLayer(tool)
          break
        // 搜索
        case 'search':
          this.handleSearch(tool)
          break
      }
    },
    infoWindowToolClick({name}) {
      const index = this.infoWindow.featureIndex;
      if (index < 0) return
      const feature = this.source.getFeatures()[index]
      switch (name) {
        // 编辑样式
        case 'editStyle':
          this.handleEditStyle()
          break
        // 编辑节点
        case 'editNode':
          this.handleEditNode(feature)
          break
        // 编辑属性
        case 'editAttribute':
          this.infoWindow.isEditAttribute = true
          break
        // 删除
        case 'delete':
          this.handleDelete(feature)
          break
        // 完成
        case 'complate':
          this.handleComplate(feature)
          break
      }
    },
    // 编辑样式
    handleEditStyle() {
      this.$refs.editStyleDialog.open()
    },
    // 编辑节点
    handleEditNode(feature) {
      // const styles = this.polygons[this.infoWindow.polygonIndex].styles
      const isEdit = feature.getProperties().edit
      feature.setProperties({
        edit: !isEdit
      })
      // this.polygons[this.infoWindow.polygonIndex].landArea = turfArea(turfPolygon([path])) / 666.6667
      if (isEdit) {
        let path = feature.getGeometry().getCoordinates()[0]
        path = path.map(item => {
          return transform(item, "EPSG:4490", "EPSG:4326");
        })
        this.polygonSetStyle(feature, this.polygonStyle)
        this.editSource.removeFeature(feature)
        this.GDMap.removeInteraction(this.modify)
        this.GDMap.removeInteraction(this.snap)
        this.polygons[this.infoWindow.polygonIndex].path = path
        const coveredPolygon = this.checkCoveredPolygon(this.polygons[this.infoWindow.polygonIndex])
        if (coveredPolygon.length > 0) {
          this.polygons[this.infoWindow.polygonIndex].parentId = coveredPolygon[0].id
          this.polygons[this.infoWindow.polygonIndex].parentIds = coveredPolygon.map(item => {
            return item.id;
          }).join(',')
        }
        this.infoWindow.extData = this.polygons[this.infoWindow.polygonIndex]
        this.transferPolygonData(this.polygons[this.infoWindow.polygonIndex].id, 'edit')
      } else {
        // 编辑多边形时关闭信息窗口
        this.infoWindow.visible = false;
        this.editSource.addFeature(feature)
        this.polygonSetStyle(feature, this.polygonStyle, 'edit')
        this.GDMap.addInteraction(this.modify) // 开启编辑
        this.GDMap.addInteraction(this.snap) // 开启自动吸附
      }
    },
    // 删除多边形
    handleDelete(feature, callBack = true) {
      // 根据ID调用接口进行删除
      const id = this.polygons[this.infoWindow.polygonIndex].id
      this.polygons.splice(this.infoWindow.polygonIndex, 1)
      this.vector.getSource().removeFeature(feature)
      this.infoWindow.visible = false
      if (callBack) {
        this.transferPolygonData(id, 'delete')
      }
    },
    // 编辑属性完成
    handleComplate(feature) {
      this.$refs["polygonForm"].validate(valid => {
        if (!valid) {
          return;
        }
        feature.setProperties({
          extData: this.infoWindow.extData,
          isNew: false
        })
        this.polygons[this.infoWindow.polygonIndex] = this.infoWindow.extData;
        this.polygonForm.forEach((v) => {
          if (this.infoWindow.extData[v.field]) {
            v.value = this.infoWindow.extData[v.field];
          } else {
            v.value = ''
          }
        })
        this.infoWindow.isEditAttribute = false
        this.transferPolygonData(this.infoWindow.extData['id'], 'edit')
      })
    },
    // 关闭信息窗
    infoWindowClose() {
      if (this.infoWindow.isEditAttribute) {
        this.infoWindow.isEditAttribute = false
      } else {
        this.infoWindow.visible = false
      }
      // 新增未填写数据时，删除多边形
      const featureIndex = this.source.getFeatures().findIndex(item => item.getId() === this.infoWindow.extData.id)
      if (featureIndex >= 0) {
        const feature = this.source.getFeatures()[featureIndex]
        const isNew = feature.getProperties().isNew
        if (isNew) {
          this.handleDelete(feature, false)
        }
        this.polygonSetStyle(feature, feature.getProperties().styles);
      }
    },
    // 地图上添加单个多边形
    addPolygon(polygon, operability = true) {
      const path = polygon.path
      if (path.length === 0) {
        //console.log("多边形没有经纬度信息")
        return false
      }
      const coordinatesPolygon = [];
      path.forEach((v) => {
        // var pointTransform = fromLonLat(v, "EPSG:3857");
        const pointTransform = transform(v, "EPSG:4326", "EPSG:4490");
        coordinatesPolygon.push(pointTransform);
      })
      const polygonFeature = new Feature({
        geometry: new Polygon([coordinatesPolygon])
      })
      // 设置extData数据，可通过getProperties获取
      polygonFeature.setProperties({
        extData: polygon,
      })
      // 设置样式
      if (polygon.styles && Object.keys(polygon.styles).length > 0) {
        let styles = {...polygon.styles, ...this.polygonStyle}
        this.polygonSetStyle(polygonFeature, styles)
        polygonFeature.setProperties({
          styles: styles
        })
      } else {
        this.polygonSetStyle(polygonFeature, this.polygonStyle)
        polygonFeature.setProperties({
          styles: this.polygonStyle
        })
      }
      // 设置id
      polygonFeature.setId(polygon.id)
      // 添加到地图显示
      this.vector.getSource().addFeature(polygonFeature)
      // this.flash(polygonFeature)

      if (operability) {
        this.polygons.push(polygon)
        // 添加点击事件
        polygonFeature.on('click', (ev) => {
          const feature = ev.target
          const point = ev.event.coordinate
          if (!this.isDrawing) {
            this.setInfoWindowPosition(feature, point)
          }
        })
      }
    },
    // 开始画多边形
    handleDrawPolygon(tool) {
      if (this.isDrawing) {
        this.GDMap.removeInteraction(this.draw)
        this.GDMap.removeInteraction(this.snap)
        this.draw.un('drawend', this.drawCompleted)
        this.isDrawing = false
        this.showMapTooltip = false
      } else {
        this.isDrawing = true
        const polygonStyle = this.polygonStyle
        this.draw = new Draw({
          type: 'Polygon',
          style: new Style({
            fill: new Fill({
              color: this.hexToRgba(polygonStyle.fillColor, polygonStyle.fillOpacity)
            }),
            stroke: new Stroke({
              color: polygonStyle.fillColor,
              width: 1
            }),
            image: new Circle({
              radius: 3,
              fill: new Fill({
                color: polygonStyle.fillColor
              })
            })
          })
        })
        this.GDMap.addInteraction(this.draw) // 开启画图
        this.GDMap.addInteraction(this.snap) // 开启自动吸附
        this.draw.on('drawend', this.drawCompleted)
      }
      tool.label = this.isDrawing ? '取消操作' : '添加区域'
    },
    // 绘画完成
    drawCompleted(ev) {
      this.drawPointCount = 0
      const feature = ev.feature
      let path = feature.getGeometry().getCoordinates()[0] // 获取多边形的path
      let pathFor4326 = [];
      path.forEach((v) => {
        const pointTransform = transform(v, "EPSG:4490", "EPSG:4326");
        pathFor4326.push(pointTransform);
      })
      const polygon = {
        id: require('uuid').v1(),
        path: pathFor4326
      }
      const coveredPolygon = this.checkCoveredPolygon(polygon)
      if (coveredPolygon.length > 0) {
        polygon.parentId = coveredPolygon[0].id
        polygon.parentIds = coveredPolygon.map(item => {
          return item.id;
        }).join(',')
      }
      //根据坐标计算面积
      polygon.landArea = turfArea(turfPolygon([pathFor4326])) / 666.6667
      this.addPolygon(polygon)
      feature.setProperties({
        extData: polygon
      })
      this.setInfoWindowPosition(feature) // 设置信息窗的位置
      this.infoWindow.isEditAttribute = true
      // 新增的多边形元素增加isNew属性
      this.source.getFeatures()[this.infoWindow.featureIndex].setProperties({
        isNew: true
      })
      setTimeout(() => {
        this.GDMap.removeInteraction(this.draw)
        this.GDMap.removeInteraction(this.snap)
        this.isDrawing = false
        this.showMapTooltip = false
      }, 20)
    },
    // 设置信息窗的位置
    setInfoWindowPosition(feature, point) {
      const center = this.getFeatureCenter(feature)
      const extData = feature.getProperties().extData
      this.infoWindow.visible = true
      this.infoWindow.polygonCenter = center
      this.infoWindow.extData = Object.assign({}, extData);
      this.infoWindow.featureIndex = this.source.getFeatures().findIndex(item => item.getId() === extData.id)
      this.infoWindow.polygonIndex = this.polygons.findIndex(item => item.id === extData.id)
      this.polygonForm.forEach((v) => {
        if (Object.keys(extData).indexOf(v.field) >= 0) {
          v.value = extData[v.field]
        } else {
          v.value = ''
        }
      })
      this.polygonSetStyle(feature, this.polygonSelectStyle);
      // this.editStyleDialog.
      // = extData.styles
      // this.editStyleDialog.polygonId = extData.id
      this.$nextTick(() => {
        this.$refs.infoWindow.adjustPos()
        if (!this.infoWindow.overlay) {
          // 设置信息窗Overlay
          this.infoWindow.overlay = new Overlay({
            element: this.$refs.infoWindow.$el
          })
          this.GDMap.addOverlay(this.infoWindow.overlay) // 地图上添加信息窗
        }
        this.infoWindow.overlay.setPosition(point || center) // 设置信息窗位置
      })
    },
    setMapTooltipPosition(pixel) {
      const x = pixel[0] + 12
      const y = pixel[1] - 12
      this.$refs.mapTooltip.style.left = x + 'px'
      this.$refs.mapTooltip.style.top = y + 'px'
    },
    // 获取多边形要素的中心坐标
    getFeatureCenter(feature) {
      const polygonGeometry = feature.getGeometry()
      const path = polygonGeometry.getCoordinates()[0] // 获取多边形的path
      // 获取多边形的中心坐标
      return getCenter(boundingExtent(path));
    },
    // 设置多边形样式，默认是添加样式，type为edit的时候为编辑样式，多边形角有圆点
    polygonSetStyle(feature, styles, type = 'add') {
      const fill = new Fill({
        color: this.hexToRgba(styles.fillColor, styles.fillOpacity)
      })
      const stroke = new Stroke({
        color: this.hexToRgba(styles.strokeColor, styles.strokeOpacity),
        width: styles.strokeWeight
      })
      const text = styles.text ? new Text({
        text: styles.text,
        fill: new Fill({
          color: styles.textFillColor ?? '#fff',
        })
      }) : null
      const style = new Style({
        fill,
        stroke,
        text
      })
      const circleStyle = new Style({
        image: new Circle({
          radius: 3,
          fill: new Fill({
            color: '#409EFF'
          })
        }),
        geometry: () => {
          const coordinates = feature.getGeometry().getCoordinates()[0]
          return new MultiPoint(coordinates)
        }
      })
      if (type === 'add') {
        feature.setStyle(style)
      } else {
        feature.setStyle([style, circleStyle])
      }
    },
    hexToRgba(hex, trans = 1) {
      let hexColor = /^#/.test(hex) ? hex.slice(1) : hex
      let r
      let g
      let b
      hexColor = /^[0-9a-f]{3}|[0-9a-f]{6}$/i.test(hexColor) ? hexColor : 'fffff'
      if (hexColor.length === 3) {
        hexColor = hexColor.replace(/(\w)(\w)(\w)/gi, '$1$1$2$2$3$3')
      }
      r = hexColor.slice(0, 2)
      g = hexColor.slice(2, 4)
      b = hexColor.slice(4, 6)
      r = parseInt(r, 16)
      g = parseInt(g, 16)
      b = parseInt(b, 16)
      return `rgba(${r}, ${g}, ${b}, ${trans})`
    },
    // 获取被覆盖的多边形
    checkCoveredPolygon(polygon) {
      let parent_ids = []
      if (this.originalPolygons.length === 0) {
        return parent_ids
      }
      this.originalPolygons.some(item => {
        if (this.isInOrOverlap(item.path, polygon.path)) {
          parent_ids.push(item);
        }
      })
      return parent_ids;
    },
    //判断是否重叠或者相交
    isInOrOverlap(originalPath, targetPath) {
      const originalPolygon = turfPolygon([originalPath])
      const targetPolygon = turfPolygon([targetPath])
      return turfBooleanOverlap(targetPolygon, originalPolygon) || turfBooleanWithin(targetPolygon, originalPolygon);
    },
    // 添加原始覆盖物
    addOriginalPolygons(polygon) {
      this.originalPolygons.push(polygon)
      this.addPolygon(polygon, false)
    },
    // 触发父组件回调方法
    transferPolygonData(id, operateType) {
      const callBackParam = {
        operateType: operateType,
        id: id,
        polygons: this.polygons
      }
      this.$emit("onChange", callBackParam)
    },
    setFeatureStyle(id, style) {
      const index = this.source.getFeatures().findIndex(item => item.getId() === id)
      if (index < 0) return
      let feature = this.source.getFeatures()[index]
      feature.setProperties({
        styles: style
      })
      this.polygonSetStyle(feature, style);
    },
    // 聚焦到多边形要素位置
    focusFeatureCenter(zoom = 15) {
      const viewer = this.GDMap.getView();
      const features = this.source.getFeatures();
      if (features.length > 0) {
        const center = this.getFeatureCenter(features[0])
        viewer.animate({
          center: center,
          zoom: zoom,
          duration: 500 // 动画时长
        })
      }
    },
    featureClear() {
      this.vector.getSource().clear();
    },
    handleSwitchLayer() {
      this.isShowLayer = !this.isShowLayer
    },
    // 底图切换
    vmChooseMapType(e) {
      // changeMapType(e, this)
    },
    handleSearch() {
      this.showSearchChange = !this.showSearchChange
    },
    contractArea() {
      let contractLand = this.vector.getSource().getFeatures();
      contractLand.forEach((v) => {
        v.getStyle().setText(
          new Text({
            text: v.landName + '\n' + v.landArea,
            fill: new Fill({
              color: '#fff',
            }),
          }),
        )
      })
    },
    // 添加自定义图层
    addCustomerLayer(layerName, extent, index = 2) {
      this.GDMap.addLayer(new TileLayer({
        extent: extent,
        source: new XYZ({
          url: 'https://map.dutkj.com/gwc/service/tms/1.0.0/dtsz%3A' + layerName + '@4490/{z}/{x}/{-y}.png',
          maxZoom: 18,
          zIndex: index
        })
      }))
    },
    // 添加图例
    addLegend(layerName) {
      const wmsSource = new ImageWMS({
        url: 'https://map.dutkj.com/dtsz/wms',
        params: {
          'LAYERS': 'dtsz:' + layerName
        },
        ratio: 1,
        serverType: 'geoserver',
      });
      this.legendUrl = wmsSource.getLegendUrl()
    }
  },
  watch: {
    drawPointCount(val) {
      if (val >= 2) {
        this.mapTooltipText = '双击完成绘制'
      } else {
        this.mapTooltipText = '单击进行绘制'
      }
    },
    "infoWindow.isEditAttribute": {
      handler(val) {
        if (!this.infoWindow.visible) {
          return false
        }
        // 编辑属性时调整信息窗的宽度，并调整信息窗的位置
        let tempWidth = "320px";
        if (val) {
          if (this.polygonForm.length === 1) {
            tempWidth = "auto";
          } else {
            tempWidth = "600px";
          }
        }
        this.$nextTick(() => {
          this.$refs['infoWindow'].tempWidth = tempWidth
          setTimeout(() => {
            this.$refs.infoWindow.adjustPos()
          }, 20)
        })
      }
    },
    showSearchChange(val) {
      if (val) {
        this.mapTools.find(item => item.name === 'search').icon = 'el-icon-close'
      } else {
        this.mapTools.find(item => item.name === 'search').icon = 'el-icon-search'
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.map {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  background-color: #f5f6f8;
  display: flex;

  .map-left {
    width: 280px;
    position: relative;

    .top {
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    .list {
      position: absolute;
      left: 18px;
      right: 18px;
      top: 54px;
      bottom: 0;
      overflow: auto;

      .list-item {
        margin-bottom: 10px;
        cursor: pointer;
        display: flex;
        align-items: center;

        .item {
          display: flex;
          align-items: center;
          flex: 1;
        }

        .item-color {
          width: 26px;
          height: 16px;
          box-sizing: border-box;
          margin-right: 5px;
          border-style: solid;
        }

        .item-name {
          font-size: 12px;
          flex: 1;
        }
      }
    }
  }

  .map-tooltip {
    position: absolute;
    border-radius: 4px;
    padding: 0 8px;
    z-index: 2000;
    font-size: 12px;
    line-height: 24px;
    min-width: 80px;
    word-wrap: break-word;
    background: rgba(48, 49, 51, 0.8);
    color: #ffffff;
    text-align: center;
    margin-left: 12px;

    &::after {
      content: "";
      width: 0;
      height: 0;
      font-size: 0;
      border-width: 5px;
      border-color: transparent rgba(48, 49, 51, 0.8) transparent transparent;
      border-style: dashed solid dashed dashed;
      overflow: hidden;
      position: absolute;
      left: -10px;
      top: 50%;
      transform: translateY(-50%);
    }
  }

  .map-content {
    //margin-left: 10px;
    //overflow: hidden;
    flex: 1;
    position: relative;

    .map-tools {
      position: absolute;
      right: 30px;
      top: 30px;
      //background: transparent;
      .tool-icon {
        font-size: 26px;
        color: #409eff;
        cursor: pointer;
        display: block;
        //background: #FFFFFF;
        padding: 10px 0;
      }
    }
  }

  .info-window-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;

    .by {
      font-size: 12px;
      color: #ccc;
    }

    .tools {
      font-size: 20px;
      color: #FFFFFF;

      .footer-icon {
        cursor: pointer;
        margin-left: 10px;
      }
    }
  }

  #GDMap {
    width: 100%;
    height: 100%;
    position: relative;
    // cursor: crosshair;
  }
}

/* 弹框 */
.dialog {
  position: absolute;
  top: 0;
  right: 0;
  width: 40vw;
  height: 30vw;
  z-index: 1001;
  background: #fff;
  overflow-y: auto;

  .title-map,
  .title-layer {
    padding: 0 15px;
    line-height: 48px;
    box-sizing: border-box;
    height: 48px;
    font-size: 14px;
    color: #727272;
    background: #f5f5f5;
  }

  .data-top {
    display: flex;
    height: 45px;
    line-height: 45px;
  }

  .data-title {
    padding-left: 20px;
    width: 60%;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
    /* text-align: right; */
  }

  .map-wrapper {
    display: flex;
    padding: 10px 15px;
    box-sizing: border-box;
  }

  .map-item {
    width: 30%;
    margin-right: 15px;
    text-align: center;
    font-size: 14px;
  }

  .map-item img {
    margin-bottom: 10px;
    width: 100%;
    object-fit: cover;
    border-radius: 5px;
    box-sizing: border-box;
  }

  .active-img {
    border: 3px solid #01aebe;
  }

  .active-txt {
    color: #01aebe;
  }
}

.mask {
  position: fixed;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  z-index: 1000;
  background: transparent;
}


.layer-list {
  padding: 10px 15px;

  li {
    margin-bottom: 40px;

    .block {
      overflow: hidden;
      font-size: 14px;
      margin-top: 10px;

      .demonstration {
        line-height: 44px;
      }

      .el-slider {
        float: right;
        width: 90%;
      }
    }

    .el-checkbox-group {
      margin-top: 10px;
    }
  }
}

/* 设置持续时间和动画函数 */
.slide-fade-enter-active,
.slide-fade-bottom-enter-active,
.slide-fade-top-enter-active,
.detail-fade-enter-active {
  transition: all .5s ease;
}

.slide-fade-leave-active,
.slide-fade-bottom-leave-active,
.slide-fade-top-leave-active,
.detail-fade-leave-active {
  transition: all .5s ease;
  /* transition: all .5s cubic-bezier(1.0, 0.5, 0.8, 1.0); */
}

.slide-fade-enter,
.slide-fade-leave-to {
  transform: translateX(70vw);
  opacity: 0;
}

.slide-fade-bottom-enter,
.slide-fade-bottom-leave-to {
  transform: translateY(185px);
  opacity: 0;
}

.slide-fade-top-enter,
.slide-fade-top-leave-to {
  transform: translateY(-48px);
  opacity: 0;
}
</style>

